package com.xflib.tool.builder;

import com.xflib.framework.ssh.HostProperties;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author koradji@163.com
 * @date 2023/10/24
 */
public class BuilderFactory {

    public final String NPM = "npm";
    public final String PNPM = "pnpm";
    public final String MVN = "mvn";

    private Map<String, BuilderAdapter> map = new HashMap<>();
    private BuilderProperties builderProperties;
    private HostProperties hostProperties;

    public BuilderFactory(BuilderProperties builderProperties, HostProperties hostProperties) {
        this.hostProperties = hostProperties;
        this.builderProperties = builderProperties;

        this.map.put(NPM, new NpmBuilder(this));
        this.map.put(MVN, new MvnBuilder(this));
        this.map.put(PNPM, new PnpmBuilder(this));
    }

    private BuilderAdapter getBuilderByGroup(String groupName) {
        BuilderAdapter result = null;

        if (!groupName.trim().isEmpty()) {
            BuilderProjectGroupProperties g = builderProperties.getGroup().stream()
                    .filter(t -> t.getGroupName().trim().equals(groupName.trim())).findAny().orElse(null);
            if (null != g) {
                result = map.get(g.getBuildingTool().toLowerCase(Locale.ROOT).trim());
            }
        }
        return result;
    }
    private BuilderAdapter getBuilderByProject(String projectName) {
        BuilderAdapter result = null;

        if (!projectName.trim().isEmpty()) {
            BuilderProjectProperties p = builderProperties.getProject().stream()
                    .filter(t -> t.getProjectName().trim().equals(projectName.trim())).findAny().orElse(null);
            if (null != p) {
                if (null == p.getBuildingTool() || p.getBuildingTool().trim().isEmpty()) {
                    result = this.getBuilderByGroup(p.getGroupName().trim());
                } else {
                    result = map.get(p.getBuildingTool().toLowerCase(Locale.ROOT).trim());
                }
            }
        }

        if (null==result) {
            throw new RuntimeException(String.format("No builder found for ", projectName));
        }

        return result;
    }

    public BuilderProperties getBuilderProperties() {
        return this.builderProperties;
    }

    public HostProperties getHostProperties() {
        return hostProperties;
    }

    public void process(BuilderArgs args) {
        if (args.getType().equals(BuilderArgs.GROUP)) {
            processGroup(args);
        } else if (args.getType().equals(BuilderArgs.PROJECT)) {
            processProject(args);
        }
    }

    private void processGroup(BuilderArgs args) {
        Arrays.asList(String.valueOf(args.getData()).split(",")).forEach(groupId -> {
            Optional.ofNullable(builderProperties.getProject().stream()
                            .filter(t -> t.getGroupName().equals(groupId.trim())).collect(Collectors.toList()))
                    .ifPresent(list -> list.forEach(project -> (this.getBuilderByProject(project.getProjectName()))
                            .process(args.cloneWithNoData().setData(project).setType(BuilderArgs.PROJECT))
                    ));
        });
    }

    private void processProject(BuilderArgs args) {
        Arrays.asList(String.valueOf(args.getData()).split(",")).forEach(projectId -> {
            Optional.ofNullable(builderProperties.getProject().stream()
                    .filter(t -> t.getProjectName().equals(projectId.trim())).collect(Collectors.toList()))
                    .ifPresent(list -> list.forEach(project -> (this.getBuilderByProject(project.getProjectName()))
                                    .process(args.cloneWithNoData().setData(project))
                    ));
        });
    }

}
